import Group from '../../sql/module/group/group'
import GroupMessage from '../../sql/module/group/groupMessage'
import MessageChanged from '../../sql/module/group/messageChanged'
import User from '../../sql/module/user/user'
import auth from '../../middlewares/auth'
import { InfoValidator, ListValidator, NoParames } from '../../validators/public'
import { Success, NotFound, NotFoundItem } from '../../code/http-exception'
import { sequelize } from '../../sql/db'
import { Op } from 'sequelize'
import Transfer from '../../sql/module/factory/transfer'
import { MessageValidator } from '../../validators/group'

User.hasOne(Group)
Group.belongsTo(User)
User.hasOne(GroupMessage)
GroupMessage.belongsTo(User)
User.hasOne(MessageChanged)
MessageChanged.belongsTo(User)
GroupMessage.hasOne(MessageChanged)
MessageChanged.belongsTo(GroupMessage)
GroupMessage.hasOne(Group)
Group.belongsTo(GroupMessage, { foreignKey: 'lastMessage', as: 'LastMessage' })
const router: Api = new Map()

//创建售后群组
router.set('/createGroup', [auth('createGroup'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const StoreItemId = v.get('query.id')
    const group = await Group.findAll({ where: { groupName: StoreItemId } })
    if (group.length) { throw new Success() }
    const transfers = await Transfer.findAll({ where: { StoreItemId } })
    const message = await GroupMessage.create({
        UserId: transfers[0].dataValues.UserId, groupName: StoreItemId, msg: '售后会话开始', type: 'text'
    })
    const Users = transfers.map(item => ({ UserId: item.dataValues.UserId, groupName: StoreItemId, lastMessage: message.dataValues.id, type: 'group' }))
    await Group.bulkCreate(Users)
    throw new Success(StoreItemId)
}])

//创建售前聊天
router.set('/createC2C', [auth('public'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const toId = v.get('query.id')
    const UserId = ctx.auth.id
    const maxId = Math.max(toId, UserId)
    const minId = Math.min(toId, UserId)
    const groupName = 'C2C' + maxId + minId
    const group = await Group.findAll({ where: { groupName } })
    if (group.length) { throw new Success(groupName) }
    const message = await GroupMessage.create({
        UserId: toId, groupName, msg: '会话开始', type: 'text'
    })
    const Users = [UserId, toId].map(item => ({ UserId: item, groupName, lastMessage: message.dataValues.id, type: 'C2C' }))
    await Group.bulkCreate(Users)
    throw new Success(groupName)
}])

//发送消息
router.set('/addMessage', [auth('public'), async (ctx, next) => {
    const v = await new MessageValidator().validate(ctx)
    const UserId = ctx.auth.id
    const groupName = v.get('body.id')
    const msg = v.get('body.msg')
    const type = v.get('body.type')
    const group = await Group.findOne({ where: { UserId, groupName } })
    if (!group) throw new NotFoundItem('群组中不存在该用户')
    const { dataValues } = await GroupMessage.create({
        UserId, groupName, msg: typeof msg === 'string' ? msg : JSON.stringify(msg), type
    })
    const message = await GroupMessage.findOne({
        where: { id: dataValues.id },
        include: { model: User, attributes: ['nickname', 'avatar', 'fullUrl'] }
    })
    const groups = await Group.findAll({ where: { groupName } })
    groups.forEach(item => item.update({ deleted: false, readed: false, lastMessage: dataValues.id }))
    await MessageChanged.bulkCreate(groups.filter(item => item.dataValues.UserId !== UserId).map(item => ({
        UserId: item.dataValues.UserId,
        GroupMessageId: message?.dataValues.id,
        groupName, type: 'add'
    })))
    throw new Success(message)
}])

//未读群组列表
router.set('/notReadgroupList', [auth('public'), async (ctx, next) => {
    const v = await new ListValidator().validate(ctx)
    const UserId = ctx.auth.id
    const limit = v.get('query.limit')

    const { rows, count } = await Group.findAndCountAll({
        where: { UserId, readed: false },
        include: [{
            model: GroupMessage, as: 'LastMessage',
            //@ts-ignore
            include: { model: User, attributes: ['nickname', 'avatar', 'fullUrl'] }
        }],
        distinct: true,
        limit: limit * 1,
        order: [['updatedAt', 'DESC']]
    })
    throw new Success({ list: rows, total: count })
}])

//群组列表
router.set('/groupList', [auth('public'), async (ctx, next) => {
    const v = await new ListValidator().validate(ctx)
    const UserId = ctx.auth.id
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')

    const { rows, count } = await Group.findAndCountAll({
        where: { UserId, deleted: false },
        include: [{
            model: GroupMessage, as: 'LastMessage',
            //@ts-ignore
            include: { model: User, attributes: ['nickname', 'avatar', 'fullUrl'] },
        }],
        distinct: true,
        limit: limit * 1,
        offset: (page_index - 1) * limit,
        order: [['updatedAt', 'DESC']]
    })
    throw new Success({ list: rows, total: count })
}])

//删除群组列表
router.set('/delete', [auth('public'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const UserId = ctx.auth.id
    const groupName = v.get('query.id')
    const group = await Group.findAll({
        where: { groupName, UserId }
    })
    if (!group) { throw new NotFound() }
    await Promise.all(group.map(item => item.update({
        deleted: true
    })))
    throw new Success('删除成功')
}])

//历史记录
router.set('/history', [auth('public'), async ctx => {
    const v = await new ListValidator().validate(ctx)
    const UserId = ctx.auth.id
    const groupName = v.get('body.groupName')
    if (!groupName) { throw new NotFoundItem('groupName不能为空') }
    const limit = v.get('query.limit')
    const page_index = v.get('query.page_index')
    const where = { groupName }
    const total = await GroupMessage.count({ where })
    if (total === 0) {
        throw new Success({ list: [], total })
    }
    const offset = total - page_index * limit
    await Group.update({ readed: true }, { where: { groupName, UserId } })
    const rows = await GroupMessage.findAll({
        attributes: { include: [[sequelize.literal('User.id=' + UserId), 'isSelf']] },
        where,
        include: [MessageChanged, { model: User, attributes: ['avatar', 'fullUrl', 'nickname'] }],
        limit: Math.min(offset + limit * 1, limit),
        offset: Math.max(offset, 0)
    })
    const ids = rows.map(item => item.dataValues.id)
    await MessageChanged.destroy({ where: { UserId, GroupMessageId: ids } })
    throw new Success({ list: rows, total })
}])

//获取新消息
router.set('/newMessage', [auth('public'), async (ctx, next) => {
    const v = await new NoParames().validate(ctx)
    const UserId = ctx.auth.id
    const groupName = v.get('body.groupName')
    if (!groupName) { throw new NotFoundItem('groupName不能为空') }
    const changed = await MessageChanged.findAll({
        where: {
            UserId, groupName
        }, include: {
            model: GroupMessage,
            attributes: { include: [[sequelize.literal('GroupMessage.UserId=' + UserId), 'isSelf']] },
            //@ts-ignore
            include: { model: User, attributes: ['avatar', 'fullUrl', 'nickname'] }
        }
    })
    const otherChanged = await MessageChanged.findAll({
        attributes: [[sequelize.col('User.nickname'), 'nickname']],
        where: {
            groupName
        }, include: { model: User, attributes: ['nickname'] }
    })
    await Group.update({ readed: true }, { where: { groupName, UserId } })
    changed.forEach(item => item.destroy())
    throw new Success({ changed: changed.map(item => ({ message: item.dataValues.GroupMessage, type: item.dataValues.type })), otherChanged })
}])

//撤回
router.set('/back', [auth('public'), async (ctx, next) => {
    const v = await new InfoValidator().validate(ctx)
    const UserId = ctx.auth.id
    const id = v.get('query.id')
    const groupMessage = await GroupMessage.findOne({
        where: {
            UserId, id, createdAt: { [Op.gte]: new Date(Date.now() - 2 * 60 * 1000) }
        }
    })
    if (!groupMessage) { throw new NotFound('消息超过2分钟不可撤回') }
    await groupMessage.update({
        type: 'delete',
        msg: ''
    })
    const groupName = groupMessage.dataValues.groupName
    const groups = await Group.findAll({ where: { groupName } })
    await MessageChanged.bulkCreate(groups.filter(item => item.dataValues.UserId !== UserId).map(item => ({
        UserId: item.dataValues.UserId,
        GroupMessageId: groupMessage.dataValues.id,
        groupName,
        type: 'back'
    })))
    throw new Success()
}])

export { router }